﻿//*************************************************************************************************
// Msbin1ContentHandler.cs
// Owner: Mahipal Kante
//
// Encode/decode MSBin1 binary format for Web Service response
// When the Web Service response is 'application/soap+msbin1 or application/msbin1'
// (binary - used by Silverlight application with WCF RIA)
//
// Copyright(c) Microsoft Corporation, 2010
//*************************************************************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.ServiceModel.Channels;
using System.IO;

namespace WebTest.WebService.Plugin.Runtime
{
    public class Msbin1ContentHandler : ContentHandler
    {
        private static readonly BufferManager _bufferManager = BufferManager.CreateBufferManager(int.MaxValue, int.MaxValue);

        public Msbin1ContentHandler(bool isSoapMessage)
        {
            soapMessage = isSoapMessage;
        }

        public override Byte[] MessageBytes
        {
            get
            {
                MemoryStream memStream = new MemoryStream();
                if (soapMessage)
                {
                    // Encrypt result back into binary data
                    XmlWriter meWrite = XmlWriter.Create(memStream);
                    meWrite.WriteRaw(this.MessageString);
                    meWrite.Flush();
                    memStream.Position = 0;

                    XmlReader meRead = XmlReader.Create(memStream);
                    Message newMessage = Message.CreateMessage(meRead, int.MaxValue, originalMessage.Version);
                    var bindingElement = new BinaryMessageEncodingBindingElement();
                    var factory = bindingElement.CreateMessageEncoderFactory();
                    using (MemoryStream memoryStream = new MemoryStream())
                    {
                        factory.Encoder.WriteMessage(newMessage, memoryStream);
                        return memoryStream.ToArray();
                    }
                }
                else
                {
                    XmlDictionaryWriter meWrite = XmlDictionaryWriter.CreateBinaryWriter(memStream);
                    XmlDocument document = StringToXml(this.MessageString);
                    document.Save(meWrite);
                    return memStream.ToArray();
                }
            }
            set
            {
                this.messageBytes = value;
                // Decrypt body bytes to string

                if (soapMessage)
                {
                    var bindingElement = new BinaryMessageEncodingBindingElement();
                    var factory = bindingElement.CreateMessageEncoderFactory();
                    originalMessage = factory.Encoder.ReadMessage(new ArraySegment<byte>(messageBytes), _bufferManager);
                    this.MessageString = originalMessage.ToString();
                }
                else
                {
                    XmlDictionaryReader reader = XmlDictionaryReader.CreateBinaryReader(messageBytes, XmlDictionaryReaderQuotas.Max);

                    XmlDocument document = new XmlDocument();
                    document.Load(reader);
                    this.MessageString = XmlToString(document);
                }
            }
        }

        public override bool IsBinary
        {
            get
            {
                return true;
            }
        }

        private byte[] messageBytes = null;
        private Message originalMessage = null;
        private bool soapMessage = false;
    }
}
